
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       battery_monitor.h
  * @author     baiyang
  * @date       2022-10-23
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include "battery_monitor_backend.h"
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
typedef void (*battery_failsafe_handler_fn_t)(const char *, const int8_t);

typedef struct battery_monitor* battery_monitor_t;

struct battery_monitor {
    /// parameters
    struct battery_monitor_params _params[MB_BATT_MONITOR_MAX_INSTANCES];

    struct BattMonitor_State      state[MB_BATT_MONITOR_MAX_INSTANCES];
    battery_monitor_backend_t     drivers[MB_BATT_MONITOR_MAX_INSTANCES];
    uint32_t                      _log_battery_bit;
    uint8_t                       _num_instances;                                     /// number of monitors

    battery_failsafe_handler_fn_t _battery_failsafe_handler_fn;
    const int8_t*                 _failsafe_priorities; // array of failsafe priorities, sorted highest to lowest priority, -1 indicates no more entries

    int8_t                        _highest_failsafe_priority; // highest selected failsafe action level (used to restrict what actions we move into)
    bool                          _has_triggered_failsafe;  // true after a battery failsafe has been triggered for the first time
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
battery_monitor_t battmonitor_get_singleton();

void battmonitor_ctor(uint32_t log_battery_bit, battery_failsafe_handler_fn_t battery_failsafe_handler_fn, const int8_t *failsafe_priorities);

// detect and initialise any available battery monitors
void battmonitor_init();

/// Read the battery voltage and current for all batteries.  Should be called at 10hz
void battmonitor_read();

/// get_type - returns battery monitor type
enum BattMonitorType battmonitor_get_type();
enum BattMonitorType battmonitor_get_type2(uint8_t instance);

void battmonitor_check_failsafes(void);
void battmonitor_checkPoweringOff(void);
float battmonitor_voltage(uint8_t instance);

// healthy - returns true if monitor is functioning
bool battmonitor_healthy();
bool battmonitor_healthy2(uint8_t instance);

/// voltage - returns battery voltage in volts
float battmonitor_voltage(uint8_t instance);

/// get voltage with sag removed (based on battery current draw and resistance)
/// this will always be greater than or equal to the raw voltage
float battmonitor_voltage_resting_estimate(uint8_t instance);

/// voltage - returns battery voltage in volts for GCS, may be resting voltage if option enabled
float battmonitor_gcs_voltage(uint8_t instance);

/// current_amps - returns the instantaneous current draw in amperes
bool battmonitor_current_amps(float *current, uint8_t instance);

/// consumed_mah - returns total current drawn since start-up in milliampere.hours
bool battmonitor_consumed_mah(float *mah, const uint8_t instance);

/// consumed_wh - returns energy consumed since start-up in Watt.hours
bool battmonitor_consumed_wh(float *wh, const uint8_t instance);

/// capacity_remaining_pct - returns true if the percentage is valid and writes to percentage argument
bool battmonitor_capacity_remaining_pct(uint8_t *percentage, uint8_t instance);

/// time_remaining - returns remaining battery time
bool battmonitor_time_remaining(uint32_t *seconds, uint8_t instance);

/// pack_capacity_mah - returns the capacity of the battery pack in mAh when the pack is full
int32_t battmonitor_pack_capacity_mah(uint8_t instance);

// return true if any battery is pushing too much power
bool battmonitor_overpower_detected();
bool battmonitor_overpower_detected2(uint8_t instance);

bool battmonitor_has_cell_voltages(const uint8_t instance);

// return the current cell voltages, returns the first monitor instances cells if the instance is out of range
const struct BattMonitor_Cells* battmonitor_get_cell_voltages(const uint8_t instance);

// returns true if there is a temperature reading
bool battmonitor_get_temperature(float *temperature, const uint8_t instance);

#if MB_TEMPERATURE_SENSOR_ENABLED
// return true when successfully setting a battery temperature from an external source by instance
bool battmonitor_set_temperature(const float temperature, const uint8_t instance);

// return true when successfully setting a battery temperature from an external source by serial_number
bool battmonitor_set_temperature_by_serial_number(const float temperature, const int32_t serial_number);
#endif // AP_TEMPERATURE_SENSOR_ENABLED

// return true if cycle count can be provided and fills in cycles argument
bool battmonitor_get_cycle_count(uint8_t instance, uint16_t *cycles);

bool battmonitor_arming_checks(size_t buflen, char *buffer);

/*
  reset battery remaining percentage for batteries that integrate to
  calculate percentage remaining
*/
bool battmonitor_reset_remaining_mask(uint16_t battery_mask, float percentage);

// Returns the mavlink charge state. The following mavlink charge states are not used
// MAV_BATTERY_CHARGE_STATE_EMERGENCY , MAV_BATTERY_CHARGE_STATE_FAILED
// MAV_BATTERY_CHARGE_STATE_UNHEALTHY, MAV_BATTERY_CHARGE_STATE_CHARGING
int8_t battmonitor_get_mavlink_charge_state(const uint8_t instance);

// Returns mavlink fault state
uint32_t battmonitor_get_mavlink_fault_bitmask(const uint8_t instance);

/// returns true if a battery failsafe has ever been triggered
bool battmonitor_has_failsafed(void);

/// returns the highest failsafe action that has been triggered
int8_t battmonitor_get_highest_failsafe_priority(void);

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



